<?php
declare(strict_types=1);

namespace App\Wxc\Service;

use App\Wxc\Concern\ManageChannelsShopApp;
use App\Wxc\Dto\ShopCfgDto;
use App\Wxc\Exceptions\NotFoundShopException;
use App\Wxc\Mapper\WxcSharerMapper;
use App\Wxc\Mapper\WxcSharerSpecMapper;
use App\Wxc\Model\WxcSharer;
use App\Wxc\Request\WxcSharerSaveRequest;
use App\Wxc\Service\Input\SharerBindInput;
use App\Wxc\Service\Input\SharerRemoveInput;
use App\Wxc\Service\Query\SharerQuery;
use App\Wxc\Service\Query\ShopCfgQuery;
use Deepwell\ChannelsShop\Api\Sharer\Enums\SharerBindStatus;
use Deepwell\ChannelsShop\Api\Sharer\Event\Payload\SharerChange;
use Deepwell\ChannelsShop\Api\Sharer\Request\BindRequest;
use Deepwell\ChannelsShop\Api\Sharer\Request\SearchRequest;
use Deepwell\EasyQuery\Concern\QueryService;
use Hyperf\Database\Model\Collection;
use Mine\Annotation\Transaction;
use Mine\Traits\ServiceTrait;

/**
 * 分享员服务类
 * @method WxcSharer|null queryOne(SharerQuery $query)
 * @method Collection<int, WxcSharer> queryList(SharerQuery $query)
 */
class WxcSharerService
{
    use ServiceTrait;
    use ManageChannelsShopApp;
    use QueryService;

    public function __construct()
    {
        $this->queryModelClassName = WxcSharer::class;
        $this->mapper = container()->get(WxcSharerMapper::class);
    }

    public function bind(SharerBindInput $input)
    {
        $client = $this->initApplicationByAppId($input->appId)->sharer;
        $req = BindRequest::from($input);
        return $client->bind($req);
    }

    public function sync()
    {
        $shopServ = container()->get(WxcShopCfgService::class);
        $getShop = new ShopCfgQuery();
        $shopConfList = $shopServ->queryList($getShop);
        if ($shopConfList->isEmpty()) {
            throw new NotFoundShopException();
        }

        $queueServ = container()->get(WxcQueueService::class);
        foreach ($shopConfList as $conf) {
            $shopCfg = ShopCfgDto::from($conf);
            $queueServ->syncSharer($shopCfg);
        }

        return ['status' => 'promise', 'message' => '同步中'];
    }

    #[Transaction]
    public function updateSpec(WxcSharerSaveRequest $data): array
    {
        // sharer表存微信端原生字段，一般不做操作
        // sharer_spec表存二次开发所需字段
        $specMapper = container()->get(WxcSharerSpecMapper::class);
        $results = [];
        foreach ($data->sharer_id_list as $sharerId) {
            // 查询sharer
            /** @var WxcSharer $sharer */
            $sharer = $this->mapper->first(['sharer_id' => $sharerId]);
            if (!$sharer) {
                $results[$sharer->sharer_id] = false;
                continue;
            }
            // spec存在则更新，否则新增
            if ($sharer->spec) {
                $updateData = $data->toArray();
                $updateData['shop_id'] = $sharer->shop_id;
                $res = $specMapper->update($sharer->spec->sharer_id, $updateData);
            } else {
                $new = $data->toArray();
                $new['shop_id'] = $sharer->shop_id;
                $new['sharer_id'] = $sharer->sharer_id;
                $new['app_id'] = $sharer->app_id;
                $res = $specMapper->save($new);
            }
            $results[$sharer->sharer_id] = boolval($res);
        }

        return $results;
    }

    public function handleChange(SharerChange $input)
    {
        // 根据app id和open id获取分享员信息
        $query = new SharerQuery();
        $query->app_id = $input->app_id;
        $query->openid = $input->openid;
        $sharer = $this->queryOne($query);

        if ($input->bind_status === SharerBindStatus::Bind) {
            $app = $this->initApplicationByAppId($input->app_id);
            $search = new SearchRequest;
            $search->openid = $input->openid;
            $searchRes = $app->sharer->search($search);
            if (!$searchRes->errcode) {
                $sharer->fill($searchRes->toArray());
                $sharer->save();
            }
        }

        if ($input->bind_status === SharerBindStatus::Unbind) {
            if ($sharer->sharer_id) {
                $sharer->delete();
            }
        }
    }

    // 移除分享员
    #[Transaction]
    public function remove(SharerRemoveInput $input)
    {
        foreach ($input->sharer_id_list as $sharerId) {
            $sharer = WxcSharer::find($sharerId);
            $sharer?->delete();
        }
    }
}